<script lang="ts" setup>
    import CustmerList from './components/custmer-list.vue'
    import TextBox from './components/text-box.vue';
    import SessionHistory from './components/session-history.vue';
    import FromcaseInfo from './components/from-case-info.vue';
    import { TOKEN_KEY,Code_KEY} from "@/enums/CacheEnum";
    import AiservAPI from "@/api/aiserv";
    import type {  DialogueList,SessionList} from "@/api/auth/types";
    import historyTalk from '@/api/historyTalk';
    import ModalScreenPopup from '../../components/modal-screen-popup.vue';
    import IdentEntity from './components/ident-entity.vue';
    import IntellectRate from './components/intellect-rate.vue';
    const props = defineProps({
		fromCaseInfoEnter: { //隐藏显示左右两边的内容 如果都不需要传false 正常聊天页面 
			type: Boolean,
			default: true,
		},
        sessionType:{//区分是 10 会话code 还是  20 坐席会话 
            type: Number,
			default: true,
        },
        auxiliaryanswer:{//辅助回答页面 其他页面传false
            type: Boolean,
			default: true,
        },
        fromInfoline:{//表单预答回答页面 其他页面传false
            type: Boolean,
			default: false,
        },
        customertran:{//客服训练页面是true 其他页面传false
            type: Boolean,
			default: true,
        },
        trainobj:{//客服训练 训练的条件
            type: Object,
            required: true,
        },
        slotsArray:{//槽位反问数组
            type:Array,
            default:[]
        },
        isShowSlots: {//槽位侧边栏项是否显示 
			type: Boolean,
			default: false,
		},
        custQualityTest: {//智能客服质检
            type: Boolean,
            default: false,
        },
	});
    const Token = <string>localStorage.getItem(TOKEN_KEY);
    const Code = <string>localStorage.getItem(Code_KEY);
    const storedObject = JSON.parse(localStorage.getItem('userInfo') || '{}');
    const loading = ref(true);
    // 请求会话列表接口参数
    const filterData = ref({
        page: '1',
        invalid:'0',
        page_size: '20',
        query_params:`[
            {"field_name":"create_by","symbol":"=","value":${storedObject.user_id}},
            {"field_name":"session_type","symbol":"=","value":${props.custQualityTest?20:10}}
        ]`,
    });
    // 请求会话列表详情参数
    const sessionData = ref({
        page: '1',
        page_size: '1000',
        session_id:'',
        session_code:'',
    });
    //用户code的值 
    const SessinoCode =ref<string>('')
    // 获取code的参数  新的用户会话
    const from = ref({
        stream:true,//是否开启流式输出
        emotion:true,//是否有表情
        welcome:true,//欢迎语
        session_type: "user"
    })
    // 获取创建新的坐席会话
    const fromseat = ref({
        stream:true,//是否开启流式输出
        request:'',
        character:'',
        certain_info:''
    })
    // 新建卡槽式反问
        const slotSeat = ref({
        stream:true,//是否开启流式输出
        slots:[],
        isLoading:false,
    })
    // 获取案件信息录入 信息
    const fromDataInfo= ref({
        address:'',
        bus_type:'',
        case_id:'',
        cat1:'',
        cat2:'',
        contact_name:'',
        phone:'',
        description:''
    })
    // 来电案件信息录入 信息
    const fromScreenPopup= ref({
        address:'',
        bus_type:'',
        case_id:'',
        cat1:'',
        cat2:'',
        contact_name:'',
        phone:'',
        description:''
    })
    // 聊天页面数组
    const dialogueList =ref<DialogueList[]>([]);
    // 历史会话列表数组
    const conversationList = ref<SessionList[]>([])
    // 流式输出是否完成   请求完成给false
    const disabledvalue = ref(false)
    // 转人工 来电弹出框
    const screenPopup = ref(false)
    // 获取新建会话的session_code
    function postsession(data:boolean){
        //  如果聊天页面是空的 不重新获取code   数组长度是1 user为空 说明有欢迎语 但是没有问答 不能重新获取最新会话
       if ((dialogueList.value.length==0||(dialogueList.value.length==1&&dialogueList.value[0].user==''))&&data) {
        ElMessage('已切换最新会话')
       }else{
            loading.value = true;
            // 点击新建时 清空页面数据   
            dialogueList.value.splice(0,dialogueList.value.length);
            const obj ={ai:'',user:'',loat:false,emotion:'',aiassist:'',ailoading:false,isshow:false,titleshow:false};
            if(props.sessionType==10){
                AiservAPI.postsession(Token,from.value).then(res=>{
                    localStorage.setItem('sessioncode', `${res.data.session_code}`);
                    SessinoCode.value = res.data.session_code;
                    // 欢迎语
                    if ( res.data.welcome) {
                        obj.ai = res.data.welcome
                        dialogueList.value.push(obj)
                    }      
                    conversationList.value.splice(0,conversationList.value.length);
                    // 请求历史会话接口   
                    historyTalk.getSessionList(Token, filterData.value).then(res => {
                        // console.log(res,"res");
                        loading.value = false;
                        conversationList.value.push(...res.data.list)
                    })
                })
            }else if(props.sessionType==20){
                // 表单预填
                if (!props.auxiliaryanswer&&!props.customertran) delete fromseat.value.certain_info
                //辅助回答
                if (props.auxiliaryanswer) {
                    fromseat.value.request='咨询家里面的水质问题';
                    fromseat.value.character='正常';
                    delete fromseat.value.certain_info
                }  
                // 客服训练   
                if (props.customertran) {
                    fromseat.value.request=props.trainobj.request;
                    fromseat.value.character=props.trainobj.character;
                    //默认加载客服训练 会调用一次 内容是空 就不让它请求接口                      
                    if (props.trainobj.request==''&&props.trainobj.trainobj=='') return
                }
                //智能客服质检
                if(props.custQualityTest){
                    fromseat.value.request='报修漏水问题';
                    fromseat.value.character='正常';
                    delete fromseat.value.certain_info;   
                }
                AiservAPI.postSeatSession(Token,fromseat.value).then(res=>{
                    localStorage.setItem('sessioncode', `${res.data.session_code}`);
                    SessinoCode.value = res.data.session_code;
                    loading.value = false;
                    if (props.custQualityTest) {
                        conversationList.value.splice(0,conversationList.value.length);
                        // 请求历史会话列表接口   
                        historyTalk.getSessionList(Token, filterData.value).then(res => {
                            loading.value = false;
                            // conversationList.value.push(...res.data.list)
                            conversationList.value=res.data.list;
                        })
                    }
                    if (!props.auxiliaryanswer&&!props.customertran&&!props.custQualityTest) {
                        const typeobj = {
                            address:'',
                            bus_type:'',
                            case_id:'',
                            cat1:'',
                            cat2:'',
                            contact_name:'',
                            phone:'',
                            description:''
                        }
                        fromDataInfo.value=Object.assign(fromDataInfo.value,typeobj)
                    }
                })
            }else if(props.sessionType==30){
                if(props.slotsArray){

                    slotSeat.value.slots= props.slotsArray;
                    //处理数据
                    const obj ={
                        slots:JSON.stringify(slotSeat.value.slots),
                        stream:true
                    }
                    if (props.slotsArray.length==0) return
                    AiservAPI.postSlotsSession(Token,obj).then(res=>{
                        // console.log('res===',res);
                        localStorage.setItem('sessioncode', `${res.data.session_code}`);
                        SessinoCode.value = res.data.session_code;
                        loading.value=false;

                })

                }
            }
       }
    }
    // 删除时更新历史会话列表
    function updateSession(index:number,data:any){
        // console.log("删除",index);
        if (data) {
            loading.value = true;
            conversationList.value.splice(0,conversationList.value.length);
            // 请求历史会话接口   
            historyTalk.getSessionList(Token, filterData.value).then(res => {
                loading.value = false;
                conversationList.value.push(...res.data.list);
                // if (index>0) {
                    activeIndex(conversationList.value[index].session_id,conversationList.value[index].session_code)
                // }                
            })
        }
    }
    // 切换历史会话列表
    function activeIndex(data:any,_code:any){
        loading.value = true;
        // sessionData.value.session_id = data;
        sessionData.value.session_code = _code;
        dialogueList.value.splice(0,dialogueList.value.length);
        historyTalk.getSessionInfo(Token,sessionData.value).then(res => {
            // console.log(res);
            localStorage.setItem('sessioncode', _code);
            SessinoCode.value = _code;
            if (res.data.list.length>0) {
                loading.value = false;
                res.data.list.map((item: {emotion: any; output_content: any; input_content: any; })=>{
                    dialogueList.value.push({loat:false,ai:item.output_content,user:item.input_content,emotion:item.emotion,aiassist:'',ailoading:false,isshow:false,titleshow:false})
                })  
            }else{
                loading.value = false;
            }
        })
    }
    // 默认调用请求 缓存页面的生命周期函数  相当于切换页面 默认第一个
    onActivated(() => {  
        postsession(false)
    })
    // 监听训练对象的改变 调用默认初始化 
    watch(() => props.trainobj, (newVal:any) => {
        if (newVal.request!=''&&newVal.character!=''&& Object.keys(newVal).length!=0) {
            postsession(false)
        }
    }, {deep: true });
    // 监听卡槽反问数组的改变 调用默认初始化 
    watch(() => props.slotsArray, (newVal:any) => {   
        // if (newVal.length>0) { 
            postsession(false)
        // }
    },{deep:true})
    // 请求AI协助函数
    async function getsearchknow(data:any){
        dialogueList.value[dialogueList.value.length-1].titleshow =false;
        dialogueList.value[dialogueList.value.length-1].ailoading=true;
        dialogueList.value[dialogueList.value.length-1].aiassist='AI正在思考...';
        // 调用接口 请求数据库回答
        const params={
            session_code: String(SessinoCode.value),
            question: String(data),
            session_type:String(props.sessionType)
        }
        const queryString = new URLSearchParams(params).toString();
        fetch(import.meta.env.VITE_APP_BASE_API+`/api/aiserv/search-knowledge?${queryString}`,{
            method: 'GET',
            headers: {
                'token':Token,
                'Content-Type': 'application/json',
                // 其他必要的 headers
            },
        }).then(response => {
            dialogueList.value[dialogueList.value.length-1].ailoading=false;
            dialogueList.value[dialogueList.value.length-1].aiassist='';
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            // 获取可读流
            const reader = response.body.getReader();
            return new ReadableStream({
                async start(controller) {
                    while(true){
                        const   { done, value} = await reader.read()
                        if (done) {
                            // 如果读取完成，关闭流
                            controller.close();
                            return;
                        }
                        dialogueList.value[dialogueList.value.length-1].aiassist +=new TextDecoder().decode(value)  
                    }
                }
            });
        }).then(stream => {
            // 可以选择将流转换为文本、JSON 或其他格式
            return new Response(stream).text();
        }).then(result => {   
            dialogueList.value[dialogueList.value.length-1].isshow=true;                     
        }).catch(error => {
            console.error('Fetch error:', error);
            return ElMessage.error("系统出错");
        });
    }
    // 提问给ai客服
    async function getsearchproblem(data:any,isref:boolean){
        // 流式输出是否完成   请求中给true 正在请求中
        disabledvalue.value = true;
        //判断是提问 还是刷新最新一条
        if (isref) {
            const obj ={ai:'',user:'',loat:true,emotion:'',aiassist:'',ailoading:false,isshow:false,titleshow:false}
            obj.user = data;
            obj.ai = '正在思考中'
            dialogueList.value.push(obj)   
        }else{
            dialogueList.value[dialogueList.value.length-1].ai='正在思考中';
            dialogueList.value[dialogueList.value.length-1].loat=true;
        }
        // 调用ai回复接口
        fetch(import.meta.env.VITE_APP_BASE_API+"/api/aiserv/answer",{
            method: 'POST',
            headers: {
                'token':Token,
                'Content-Type': 'application/json',
                // 其他必要的 headers
            },
            body: JSON.stringify({
                session_code: SessinoCode.value,
                question: data.replace(/\n/g, ''),
                session_type:props.sessionType
            }), // 将数据转换为 JSON 字符串
        }).then(response => {
            dialogueList.value[dialogueList.value.length-1].loat=false;
            dialogueList.value[dialogueList.value.length-1].ai='';
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            // 获取可读流
            const reader = response.body.getReader();
            // 初始化一个变量来跟踪是否跳过了前两个字符
            let hasSkippedFirstTwoChars = false;
            return new ReadableStream({
                async start(controller) {
                    while(true){
                        const   { done, value} = await reader.read()
                        if (done) {
                            // 如果读取完成，关闭流
                            controller.close();
                            return;
                        }
                        // 如果是code 表情是true 会话code 才会进行操作
                        if (from.value.emotion==true&&!hasSkippedFirstTwoChars&&props.sessionType==10) {
                            switch (new TextDecoder().decode(value).slice(0, 2)) {
                                case '愤怒':
                                    dialogueList.value[dialogueList.value.length-1].emotion = new TextDecoder().decode(value).slice(0, 2);
                                    break;
                                case '稍有'://稍有不满
                                    dialogueList.value[dialogueList.value.length-1].emotion = new TextDecoder().decode(value).slice(0, 4);
                                    break;
                                case '辱骂':
                                    dialogueList.value[dialogueList.value.length-1].emotion = new TextDecoder().decode(value).slice(0, 2);
                                    break;
                                case '高兴':
                                    dialogueList.value[dialogueList.value.length-1].emotion = new TextDecoder().decode(value).slice(0, 2);
                                    break;
                                case '不耐'://不耐烦
                                    dialogueList.value[dialogueList.value.length-1].emotion = new TextDecoder().decode(value).slice(0, 3);
                                    break;
                                case '一般':
                                    dialogueList.value[dialogueList.value.length-1].emotion = new TextDecoder().decode(value).slice(0, 2);
                                    break;
                                default:
                                dialogueList.value[dialogueList.value.length-1].emotion ='';
                                    break;
                            }
                            if (new TextDecoder().decode(value).slice(0, 2)=='稍有') {
                                dialogueList.value[dialogueList.value.length-1].ai +=new TextDecoder().decode(value).substring(4); 
                            }else if (new TextDecoder().decode(value).slice(0, 2)=='不耐') {
                                dialogueList.value[dialogueList.value.length-1].ai +=new TextDecoder().decode(value).substring(3);
                            }else{
                                dialogueList.value[dialogueList.value.length-1].ai +=new TextDecoder().decode(value).substring(2);
                            }
                            hasSkippedFirstTwoChars = true;
                        }else{
                            dialogueList.value[dialogueList.value.length-1].ai +=new TextDecoder().decode(value)  
                        }                            
                    }
                }
            });
        }).then(stream => {
            // 可以选择将流转换为文本、JSON 或其他格式
            return new Response(stream).text();
        }).then(result => {            
            //转人工 来电弹屏 如果ai回复有人工客服的转接 默认弹出来电弹窗
            if (props.sessionType==10&&dialogueList.value[dialogueList.value.length-1].ai.indexOf('人工客服')!=-1) screenPopup.value = true;
            // 处理结果 全部读取完成 把disabledvalue 变成false 继续提问o
            disabledvalue.value = false;
            // 表单预填  AI回复 请求接口 拿到code返回的信息  
            if (props.sessionType==20&&props.fromInfoline) {
                AiservAPI.postSeatInfo(Token,SessinoCode.value,props.sessionType).then(res=>{
                        fromDataInfo.value=Object.assign(fromDataInfo.value,res.data)
                })
            }
            //获取案件信息
            if (screenPopup.value) {
                AiservAPI.hostorySession(Token,SessinoCode.value).then(res=>{
                    fromScreenPopup.value=Object.assign(fromScreenPopup.value,res.data)
                })
            }
            // 辅助回答  点击请求AI协助
            if (props.sessionType==20&&props.auxiliaryanswer&&!props.customertran) {
                dialogueList.value[dialogueList.value.length-1].titleshow =true;
                dialogueList.value[dialogueList.value.length-1].aiassist ='请求AI协助';
            }
            if(props.sessionType==30 && props.isShowSlots){
                slotSeat.value.isLoading=true;
                AiservAPI.getAIservSlots(Token,SessinoCode.value,props.sessionType).then(res=>{
                    // console.log('res===',res);
                    // 赋值给子组件颜色数组

                    slotSeat.value.slots = res.data;
                    slotSeat.value.isLoading=false;
                })

            }
        }) .catch(error => {
            console.error('Fetch error:', error);
           return ElMessage.error("系统出错");
        });
        
    }
</script>

<!-- AI页面 -->
<template>
    <section  class="w-full h-full  flex" v-loading="loading">
        <!-- AI历史会话 -->
        <SessionHistory v-show="(!props.fromCaseInfoEnter&&props.sessionType==10) || props.custQualityTest"
            @activeIndex="activeIndex"
            @updateSession="updateSession"
            :disabledvalue="disabledvalue"
            v-model:SessinoCode="SessinoCode"
            v-model:conversationList="conversationList" 
        />
        <!-- AI对话页面 -->
        <div class="flex center-list">
            <div class="w-full m-auto h-full flex flex-col relative" >
                <CustmerList 
                :dialogueList="dialogueList" 
                :customertran="props.customertran"  
                :sessionType="props.sessionType"
                :isShowSlots="props.isShowSlots"
                :custQualityTest="props.custQualityTest"
                :disabledvalue="disabledvalue"
                @aiassist="getsearchknow"
                @addsession="postsession"
                @refresh="getsearchproblem"
                />
                <TextBox @searchtext="getsearchproblem"  :disabledvalue="disabledvalue" />
            </div>
        </div>
        <!-- 表单预填 案件信息 -->
        <FromcaseInfo v-show="props.fromCaseInfoEnter" :fromDataInfo="fromDataInfo" /> 
        <!-- 来电弹窗 -->
        <ModalScreenPopup  v-show="screenPopup" v-model:screenPopup="screenPopup" :fromScreenPopup="fromScreenPopup"  v-model:SessinoCode="SessinoCode" />
        <!-- 需要提取的实体 -->
        <IdentEntity v-show="props.isShowSlots" :isShowSlotsData="slotSeat" /> 
        <!-- 客服质检 -->
        <IntellectRate v-show="props.custQualityTest" :isShowRateData="SessinoCode"/>
    </section>
</template>

<style scoped>
.center-list{
    flex: 1;
}
</style>